package db_main

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"longmen/server/config/global"
	global2 "longmen/server/config/global"
	_const "longmen/server/pkg/common/helper/const"
	utils2 "longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql"
	"longmen/server/pkg/db/mysql/models/models_main"
	"time"

	"github.com/olivere/elastic/v7"
	"gorm.io/gorm"
)

func GetMaxId() int64 {
	table := mysql.GetRTable(&models_main.ChatHistory{})
	o := new(models_main.ChatHistory)
	mysql.Condition(table, nil, "", "id desc", 0, 0)
	err := table.Select("id").First(o).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		err = nil
	}
	return o.Id
}

// insert to ElasticSearch
func InsertEsChatHistory(chat *models_main.ChatHistory) error {
	fName := "InsertChatHistory"
	key := fmt.Sprintf("%d_%d", chat.RoomId, chat.Id)
	global2.Log.Debugf("InsertEsChatHistory key:%v,chatData:%+v", key, chat)
	resp, err := global2.GetEs().Index().Index(_const.ES_CHAT_HISTORY).
		Id(key).
		BodyJson(chat).Do(context.Background())

	if err != nil {
		return fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	global2.Log.Debug("insert im history to ES resp = ", resp)
	return nil
}

// update from ElasticSearch
// 删除一个消息
func DeleteEsChatHistoryById(roomId int, chatId int) error {
	fName := "DeleteEsChatHistoryById"
	key := fmt.Sprintf("%d_%d", roomId, chatId)
	oEs := global2.GetEs()
	if oEs == nil {
		global2.Log.Warnf("no es inited")
		return fmt.Errorf("%s", "no es inited")
	}
	resp, err := oEs.Update().Index(_const.ES_CHAT_HISTORY).
		Id(key).Doc(map[string]interface{}{"status": 0}).
		Do(context.Background())

	if err != nil {
		return fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
	}
	global2.Log.Debug("delete im history resp = ", resp)
	return nil
}

func GetEsChatHistoryByTimeRange(roomId int, startTime, endTime int64, page int) ([]*models_main.ChatHistory, error) {
	size := 100
	var from int
	if page >= 1 {
		from = (page - 1) * size
	}
	oEs := global2.GetEs()
	if oEs == nil {
		global2.Log.Warnf("no es inited")
		return nil, fmt.Errorf("%s", "no es inited")
	}
	matchQuery := elastic.NewTermQuery("room_id", roomId)
	rangeQuery := elastic.NewRangeQuery("create_time").Gte(startTime).Lte(endTime)
	boolQuery := elastic.NewBoolQuery().Filter(matchQuery, rangeQuery)
	res, err := oEs.Search(_const.ES_CHAT_HISTORY).
		Query(boolQuery).
		From(from).
		Size(size).
		TrackTotalHits(false). // 避免计算所有匹配的总数，提升性能
		Do(context.Background())
	if err != nil {
		global2.Log.Errorf("search error: %v", err)
		return nil, err
	}

	var records []*models_main.ChatHistory
	if res.Hits.TotalHits.Value > 0 {
		for _, hit := range res.Hits.Hits {
			var item *models_main.ChatHistory
			if err := json.Unmarshal(hit.Source, &item); err != nil {
				//global2.Log.Errorf("反序列化文档源出错: %s,content:%s", err, string(hit.Source))
				continue
			}
			//fmt.Println(item)
			records = append(records, item)
		}
	}

	return records, nil
}

// 删除某个房间消息
func DeleteEsChatHistoryByRoom(roomId int) error {
	oEs := global2.GetEs()
	if oEs == nil {
		global2.Log.Warnf("no es inited")
		return fmt.Errorf("%s", "no es inited")
	}
	fieldToUpdate := "status"
	updateByQuery := elastic.NewUpdateByQueryService(oEs).
		Index(_const.ES_CHAT_HISTORY).
		Query(elastic.NewTermQuery("room_id", roomId)).
		Script(elastic.NewScriptInline("ctx._source."+fieldToUpdate+" = params.newValue").Param("newValue", 0)).
		Refresh("true")
	response, err := updateByQuery.Do(context.Background())
	if err != nil {
		return err
	}
	// 检查更新结果
	if response.Updated == 0 {
		return errors.New("没有符合条件的文档需要更新")
	}
	global2.Log.Debugf("更新了 %d 个文档", response.Updated)
	return nil
}

// update from ElasticSearch
// 删除用户的消息
func DeleteEsChatHistoryByRoomIdUserId(uid int) error {
	fName := "DeleteEsChatHistoryById"
	query := elastic.NewMatchQuery("user_id", fmt.Sprint(uid))
	query1 := elastic.NewMatchQuery("status", "1")

	q := elastic.NewBoolQuery().Should().Filter(query).Filter(query1)
	iRetry := 1
	for {
		iRetry--
		time.Sleep(time.Second)
		resp, err := global2.GetEs().UpdateByQuery().
			Index(_const.ES_CHAT_HISTORY).Query(q).Script(
			elastic.NewScriptInline("ctx._source.status='0'")).
			Do(context.Background())

		if err != nil {
			return fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
		}
		global2.Log.Debugf("%d, delete im history resp =%+v ", iRetry, resp)

		for _, v := range resp.Failures {
			respRetry, err := global2.GetEs().Update().Index(_const.ES_CHAT_HISTORY).
				Id(v.Id).Doc(map[string]interface{}{"status": 0}).
				Do(context.Background())
			if err != nil {
				return fmt.Errorf("%s%s", utils2.Convert(fName), err.Error())
			}
			global2.Log.Debugf("delete im history resp =%+v", respRetry)
		}

		if resp.Total-resp.Updated == 0 || iRetry <= 0 { //全部处理完了，或者retry的次数达到了
			break
		}

	}
	return nil
}

// 结整活动统计
func ActivityBarrageStat(roomID int, liveid int64) error {
	var abid int
	err := global.GetR().Model(&models_main.ActivityBarrage{}).Where("status=1").Pluck("id", &abid).Error
	if err != nil {
		global.Log.Infof("Activity Error: %s", err.Error())
	}

	key := fmt.Sprintf("ACTIVITY_STAT_%d_%d_%d", roomID*100, abid, liveid)
	log.Println("ActivityBarrageStat=====>key:", key)
	rets, _ := global.GetRds().HGetAll(key).Result()
	// cloudData.ActivitySum = len(rets)

	err = global.GetX().Model(&models_main.ActivityBarrageStat{}).Create(&models_main.ActivityBarrageStat{
		ABID:   abid,
		Time:   time.Now().Unix(),
		Liveid: liveid,
		Sum:    int64(len(rets)),
	}).Error

	return err
}
